<!DOCTYPE HTML>
<html>

<head>
	<link rel="bookmark"  type="image/x-icon"  href="/img/logo_miccall.png"/>
	<link rel="shortcut icon" href="/img/logo_miccall.png">
	
			    <title>
    Ame雨
    </title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
    <link rel="stylesheet" href="/amelin-ting/css/mic_main.css" />
    <link rel="stylesheet" href="/amelin-ting/css/dropdownMenu.css" />
    <meta name="keywords" content="Ame雨" />
    
    	<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
	 
    <noscript>
        <link rel="stylesheet" href="/amelin-ting/css/noscript.css" />
    </noscript>
    <style type="text/css">
        body:before {
          content: ' ';
          position: fixed;
          top: 0;
          background: url('/amelin-ting/img/bg.jpg') center 0 no-repeat;
          right: 0;
          bottom: 0;
          left: 0;
          background-size: cover; 
        }
    </style>

			    
  
    <script type="text/x-mathjax-config">
      MathJax.Hub.Config({
        tex2jax: {
          inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
          processEscapes: true,
          skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
        }
      });
    </script>

    <script type="text/x-mathjax-config">
      MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for (i=0; i < all.length; i += 1) {
          all[i].SourceElement().parentNode.className += ' has-jax';
        }
      });
    </script>
    <script async type="text/javascript" src="//cdn.bootcss.com/mathjax/2.7.1/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
  


    <script src="/amelin-ting/js/jquery.min.js"></script>
    <script src="/amelin-ting/js/jquery.scrollex.min.js"></script>
    <script src="/amelin-ting/js/jquery.scrolly.min.js"></script>
    <script src="/amelin-ting/js/skel.min.js"></script>
    <script src="/amelin-ting/js/util.js"></script>
    <script src="/amelin-ting/js/main.js"></script>
	
<meta name="generator" content="Hexo 5.4.0"></head>
    
		
<!-- Layouts -->



<!--  代码渲染  -->
<link rel="stylesheet" href="/css/prism_coy.css" />
<link rel="stylesheet" href="/css/typo.css" />
<!-- 文章页 -->
<body class="is-loading">
    <!-- Wrapper 外包 s-->
    <div id="wrapper" class="fade-in">
        <!-- Intro 头部显示 s -->
        <!-- Intro 头部显示 e -->
        <!-- Header 头部logo start -->
        <header id="header">
    <a href="/amelin-ting/" class="logo">Art Space</a>
</header>
        <!-- Nav 导航条 start -->
        <nav id="nav" class="special" >
            <ul class="menu links" >
			<!-- Homepage  主页  --> 
			<li >
	            <a href="/amelin-ting/" rel="nofollow">主页</a>
	        </li>
			<!-- categories_name  分类   --> 
	        
	        <li class="active">
	            <a href="#s1">分类</a>
	                    <ul class="submenu">
	                        <li>
	                        <a class="category-link" href="/amelin-ting/categories/Go/">Go</a></li><li><a class="category-link" href="/amelin-ting/categories/django/">django</a></li><li><a class="category-link" href="/amelin-ting/categories/drf/">drf</a></li><li><a class="category-link" href="/amelin-ting/categories/gin/">gin</a></li><li><a class="category-link" href="/amelin-ting/categories/go/">go</a></li><li><a class="category-link" href="/amelin-ting/categories/linux/">linux</a></li><li><a class="category-link" href="/amelin-ting/categories/mysql/">mysql</a></li><li><a class="category-link" href="/amelin-ting/categories/python/">python</a></li><li><a class="category-link" href="/amelin-ting/categories/%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F/">内网穿透</a></li><li><a class="category-link" href="/amelin-ting/categories/%E5%89%8D%E7%AB%AF/">前端</a>
	                    </ul>
	        </li>
	        
	        <!-- archives  归档   --> 
	        
	        
		        <!-- Pages 自定义   -->
		        
		        <li>
		            <a href="/about/" title="简历">
		                简历
		            </a>
		        </li>
		        
		        <li>
		            <a href="/group/" title="团队">
		                团队
		            </a>
		        </li>
		        
		        <li>
		            <a href="/gallery/" title="图库">
		                图库
		            </a>
		        </li>
		        
		        <li>
		            <a href="/tag/" title="标签">
		                标签
		            </a>
		        </li>
		        


            </ul>
            <!-- icons 图标   -->
			<ul class="icons">
                    
                    <li>
                        <a title="github" href="https://github.com/miccall" target="_blank" rel="noopener">
                            <i class="icon fa fa-github"></i>
                        </a>
                    </li>
                    
                    <li>
                        <a title="500px" href="http://500px.com" target="_blank" rel="noopener">
                            <i class="icon fa fa-500px"></i>
                        </a>
                    </li>
                    
			</ul>
</nav>

        <div id="main" >
            <div class ="post_page_title_img" style="height: 25rem;background-image: url(https://img0.baidu.com/it/u=3654521039,2322759323&amp;fm=26&amp;fmt=auto);background-position: center; background-repeat:no-repeat; background-size:cover;-moz-background-size:cover;overflow:hidden;" >
                <a href="#" style="padding: 4rem 4rem 2rem 4rem ;"><h2 >Go单元测试</h2></a>
            </div>
            <!-- Post -->
            <div class="typo" style="padding: 3rem;">
                <h2 id="一、go-test工具"><a href="#一、go-test工具" class="headerlink" title="一、go test工具"></a>一、go test工具</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Go语言中的测试依赖go test 命令。</span></span><br><span class="line"><span class="comment">// 不用担心，编写测试代码和编写普通代码都是类似的、</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">go test命令是一个按照一定约定和组织的测试代码的驱动程序。</span></span><br><span class="line"><span class="comment">在包目录内，所有以_test.go为后缀名的源代码文件都是go test测试的一部分，不会被go build编译到最终的可执行文件中。</span></span><br><span class="line"><span class="comment">在*_test.go文件中有三种类型的函数，单元测试函数。基准测试函数和实力函数。</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">测试函数	函数名前缀为Test	测试程序的一些逻辑行为是否正确</span></span><br><span class="line"><span class="comment">基准函数	函数名前缀为Benchmark	测试函数的性能</span></span><br><span class="line"><span class="comment">示例函数	函数名前缀为Example	为文档提供示例文档</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">go test命令会遍历所有的*_test.go文件中符合上述命名规则的函数，然后生成一个临时的main包用于调用相应的测试函数，然后构建并运行。报告测试结果，最后清理测试中生成的临时文件。</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>

<h2 id="二、测试函数"><a href="#二、测试函数" class="headerlink" title="二、测试函数"></a>二、测试函数</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 每个测试函数必须导入testing包</span></span><br><span class="line"><span class="comment">// 测试函数的名字必须以Test开头，可选的后缀名必须以大写字母开头</span></span><br><span class="line"></span><br><span class="line"><span class="number">1.</span> 代码演示</span><br><span class="line"><span class="comment">// split.go</span></span><br><span class="line">    <span class="keyword">package</span> split_str</span><br><span class="line"></span><br><span class="line">    <span class="keyword">import</span> <span class="string">&quot;strings&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">Split</span><span class="params">(str, sep <span class="keyword">string</span>)</span> []<span class="title">string</span></span> &#123;</span><br><span class="line">        <span class="keyword">var</span> ret []<span class="keyword">string</span></span><br><span class="line">        index := strings.Index(str, sep)</span><br><span class="line">        <span class="keyword">for</span> index &gt;= <span class="number">0</span> &#123;</span><br><span class="line">            ret = <span class="built_in">append</span>(ret, str[: index])</span><br><span class="line">            str = str[index + <span class="built_in">len</span>(sep):]</span><br><span class="line">            index = strings.Index(str, sep)</span><br><span class="line">        &#125;</span><br><span class="line">        ret = <span class="built_in">append</span>(ret, str)</span><br><span class="line">        <span class="keyword">return</span> ret</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// split_test.go</span></span><br><span class="line">    <span class="keyword">package</span> split_str</span><br><span class="line"></span><br><span class="line">    <span class="keyword">import</span> (</span><br><span class="line">        <span class="string">&quot;reflect&quot;</span></span><br><span class="line">        <span class="string">&quot;testing&quot;</span></span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">TestSplit</span><span class="params">(t *testing.T)</span></span> &#123;</span><br><span class="line">        ret := Split(<span class="string">&quot;a:b:c&quot;</span>, <span class="string">&quot;:&quot;</span>)</span><br><span class="line">        want := []<span class="keyword">string</span>&#123;<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>&#125;</span><br><span class="line">        <span class="keyword">if</span> !reflect.DeepEqual(ret, want) &#123;</span><br><span class="line">            t.Errorf(<span class="string">&quot;want: %v bou got: %v&quot;</span>, want, ret)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">Test2Split</span><span class="params">(t *testing.T)</span></span> &#123;</span><br><span class="line">        ret := Split(<span class="string">&quot;abcbabdfyh&quot;</span>, <span class="string">&quot;:&quot;</span>)</span><br><span class="line">        want := []<span class="keyword">string</span>&#123;<span class="string">&quot;a&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;a&quot;</span>, <span class="string">&quot;asdf&quot;</span>&#125;</span><br><span class="line">        <span class="keyword">if</span> !reflect.DeepEqual(ret, want) &#123;</span><br><span class="line">            t.Errorf(<span class="string">&quot;want: %v bou got: %v&quot;</span>, want, ret)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">命令行输出：</span></span><br><span class="line"><span class="comment">    === RUN   TestSplit</span></span><br><span class="line"><span class="comment">    --- PASS: TestSplit (0.00s)</span></span><br><span class="line"><span class="comment">    === RUN   Test2Split</span></span><br><span class="line"><span class="comment">        split_test.go:20: want: [a c a asdf] bou got: [abcbabdfyh]</span></span><br><span class="line"><span class="comment">    --- FAIL: Test2Split (0.00s)</span></span><br><span class="line"><span class="comment">    FAIL</span></span><br><span class="line"><span class="comment">    exit status 1</span></span><br><span class="line"><span class="comment">    FAIL    day7/split_str  0.072s</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>

<h2 id="三、测试组"><a href="#三、测试组" class="headerlink" title="三、测试组"></a>三、测试组</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 测试组其实就是封装的思想，减少重复代码，增加可阅读性</span><br><span class="line">    <span class="keyword">package</span> split_str</span><br><span class="line"></span><br><span class="line">    <span class="keyword">import</span> (</span><br><span class="line">        <span class="string">&quot;reflect&quot;</span></span><br><span class="line">        <span class="string">&quot;testing&quot;</span></span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">TestSplit</span><span class="params">(t *testing.T)</span></span> &#123;</span><br><span class="line">        <span class="comment">// 定义一个测试用例类型</span></span><br><span class="line">        <span class="keyword">type</span> test <span class="keyword">struct</span>&#123;</span><br><span class="line">            str <span class="keyword">string</span></span><br><span class="line">            ret <span class="keyword">string</span></span><br><span class="line">            want []<span class="keyword">string</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        testGroup := []test&#123;</span><br><span class="line">            test&#123;<span class="string">&quot;a:b:c&quot;</span>, <span class="string">&quot;:&quot;</span>, []<span class="keyword">string</span>&#123;<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>&#125;&#125;,</span><br><span class="line">            test&#123;<span class="string">&quot;abcbabdfyh&quot;</span>, <span class="string">&quot;:&quot;</span>, []<span class="keyword">string</span>&#123;<span class="string">&quot;a&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;a&quot;</span>, <span class="string">&quot;dfyh&quot;</span>&#125;&#125;,</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> _, tc := <span class="keyword">range</span> testGroup &#123;</span><br><span class="line">            got := Split(tc.str, tc.ret)</span><br><span class="line">            <span class="keyword">if</span> !reflect.DeepEqual(got, tc.want) &#123;</span><br><span class="line">                t.Fatalf(<span class="string">&quot;want: %#v  got: %#v&quot;</span>, tc.want, got)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="comment">// 这么看其实代码少写了很多，但是也有一个缺点，对于报错的具体位置变得不清晰了，所以Go又提供了一个子测试</span></span><br><span class="line"></span><br><span class="line"><span class="number">2.</span> 子测试</span><br><span class="line">    <span class="keyword">package</span> split_str</span><br><span class="line"></span><br><span class="line">    <span class="keyword">import</span> (</span><br><span class="line">        <span class="string">&quot;reflect&quot;</span></span><br><span class="line">        <span class="string">&quot;testing&quot;</span></span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">TestSplit</span><span class="params">(t *testing.T)</span></span> &#123;</span><br><span class="line">        <span class="comment">// 定义一个测试用例类型</span></span><br><span class="line">        <span class="keyword">type</span> testCase <span class="keyword">struct</span>&#123;</span><br><span class="line">            str <span class="keyword">string</span></span><br><span class="line">            ret <span class="keyword">string</span></span><br><span class="line">            want []<span class="keyword">string</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        testGroup := <span class="keyword">map</span>[<span class="keyword">string</span>]testCase&#123;</span><br><span class="line">            <span class="string">&quot;case_1&quot;</span>:testCase&#123;<span class="string">&quot;a:b:c&quot;</span>, <span class="string">&quot;:&quot;</span>, []<span class="keyword">string</span>&#123;<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>&#125;&#125;,</span><br><span class="line">            <span class="string">&quot;case_2&quot;</span>:testCase&#123;<span class="string">&quot;abcbabdfyh&quot;</span>, <span class="string">&quot;:&quot;</span>, []<span class="keyword">string</span>&#123;<span class="string">&quot;a&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;a&quot;</span>, <span class="string">&quot;d1yh&quot;</span>&#125;&#125;,</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> name, tc := <span class="keyword">range</span> testGroup &#123;</span><br><span class="line">            t.Run(name, <span class="function"><span class="keyword">func</span><span class="params">(t *testing.T)</span></span> &#123;</span><br><span class="line">                got := Split(tc.str, tc.ret)</span><br><span class="line">                <span class="keyword">if</span> !reflect.DeepEqual(got, tc.want) &#123;</span><br><span class="line">                    t.Fatalf(<span class="string">&quot;want: %#v  got: %#v&quot;</span>, tc.want, got)</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h2 id="四、测试覆盖率"><a href="#四、测试覆盖率" class="headerlink" title="四、测试覆盖率"></a>四、测试覆盖率</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">    测试覆盖率是你的代码被测试套件覆盖的百分比。通常我们使用的都是语句的覆盖率，也就是在测试中至少被运行一次的代码占总代码的比例。</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    Go提供内置功能来检查你的代码覆盖率。我们可以使用go test -cover来查看测试覆盖率。例如：</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    split $ go test -cover</span></span><br><span class="line"><span class="comment">    PASS</span></span><br><span class="line"><span class="comment">    coverage: 100.0% of statements</span></span><br><span class="line"><span class="comment">    ok      github.com/Q1mi/studygo/code_demo/test_demo/split       0.005s</span></span><br><span class="line"><span class="comment">    从上面的结果可以看到我们的测试用例覆盖了100%的代码。</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    Go还提供了一个额外的-coverprofile参数，用来将覆盖率相关的记录信息输出到一个文件。例如：</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    split $ go test -cover -coverprofile=c.out</span></span><br><span class="line"><span class="comment">    PASS</span></span><br><span class="line"><span class="comment">    coverage: 100.0% of statements</span></span><br><span class="line"><span class="comment">    ok      github.com/Q1mi/studygo/code_demo/test_demo/split       0.005s</span></span><br><span class="line"><span class="comment">    上面的命令会将覆盖率相关的信息输出到当前文件夹下面的c.out文件中，然后我们执行go tool cover -html=c.out，使用cover工具来处理生成的记录信息，该命令会打开本地的浏览器窗口生成一个HTML报告。</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>



<h2 id="五、性能基准测试"><a href="#五、性能基准测试" class="headerlink" title="五、性能基准测试"></a>五、性能基准测试</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 基准测试</span><br><span class="line">    <span class="keyword">package</span> split_str</span><br><span class="line"></span><br><span class="line">    <span class="keyword">import</span> (</span><br><span class="line">        <span class="string">&quot;testing&quot;</span></span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">BenchmarkSplit</span><span class="params">(b *testing.B)</span></span> &#123;</span><br><span class="line">        <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; b.N; i++ &#123;</span><br><span class="line">            Split(<span class="string">&quot;a:b:c:b:c&quot;</span>, <span class="string">&quot;:&quot;</span>)</span><br><span class="line">        &#125; </span><br><span class="line">    &#125;</span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	基准结果不会默认执行的，我们得增加-bench参数，所以我们通过go test -bench=Split执行基准测试，输出结果如下:</span></span><br><span class="line"><span class="comment">	</span></span><br><span class="line"><span class="comment">	goos: windows</span></span><br><span class="line"><span class="comment">	goarch: amd64</span></span><br><span class="line"><span class="comment">	pkg: day7/split_str</span></span><br><span class="line"><span class="comment">	cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz</span></span><br><span class="line"><span class="comment">	BenchmarkSplit-8         1339820              1112 ns/op</span></span><br><span class="line"><span class="comment">	PASS</span></span><br><span class="line"><span class="comment">	ok      day7/split_str  2.486s</span></span><br><span class="line"><span class="comment">	</span></span><br><span class="line"><span class="comment">	我们也可以最后再加一个-benchmem参数，来获得内存分配的统计数据</span></span><br><span class="line"><span class="comment">	</span></span><br><span class="line"><span class="comment">	goos: windows</span></span><br><span class="line"><span class="comment">    goarch: amd64</span></span><br><span class="line"><span class="comment">    pkg: day7/split_str</span></span><br><span class="line"><span class="comment">    cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz</span></span><br><span class="line"><span class="comment">    BenchmarkSplit-8         2908327               376.9 ns/op           240 B/op          4 allocs/op</span></span><br><span class="line"><span class="comment">    PASS</span></span><br><span class="line"><span class="comment">    ok      day7/split_str  1.607s</span></span><br><span class="line"><span class="comment">    </span></span><br><span class="line"><span class="comment">    其中，240 B/op表示每次操作内存分配了112字节，4 allocs/op则表示每次操作进行了3次内存分配</span></span><br><span class="line"><span class="comment">	*/</span></span><br><span class="line"></span><br><span class="line"><span class="number">2.</span> 切片优化上述代码</span><br><span class="line">    <span class="keyword">package</span> split_str</span><br><span class="line"></span><br><span class="line">    <span class="keyword">import</span> <span class="string">&quot;strings&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">Split</span><span class="params">(str, sep <span class="keyword">string</span>)</span> []<span class="title">string</span></span> &#123;</span><br><span class="line">        <span class="keyword">var</span> ret []<span class="keyword">string</span> = <span class="built_in">make</span>([]<span class="keyword">string</span>, <span class="number">0</span>, strings.Count(str, sep) + <span class="number">1</span>)</span><br><span class="line">        index := strings.Index(str, sep)</span><br><span class="line">        <span class="keyword">for</span> index &gt;= <span class="number">0</span> &#123;</span><br><span class="line">            ret = <span class="built_in">append</span>(ret, str[: index])</span><br><span class="line">            str = str[index + <span class="built_in">len</span>(sep):]</span><br><span class="line">            index = strings.Index(str, sep)</span><br><span class="line">        &#125;</span><br><span class="line">        ret = <span class="built_in">append</span>(ret, str)</span><br><span class="line">        <span class="keyword">return</span> ret</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">    再一次命令行输出：</span></span><br><span class="line"><span class="comment">    goos: windows</span></span><br><span class="line"><span class="comment">    goarch: amd64</span></span><br><span class="line"><span class="comment">    pkg: day7/split_str</span></span><br><span class="line"><span class="comment">    cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz</span></span><br><span class="line"><span class="comment">    BenchmarkSplit-8         5040412               199.5 ns/op            80 B/op          1 allocs/op</span></span><br><span class="line"><span class="comment">    PASS</span></span><br><span class="line"><span class="comment">    ok      day7/split_str  1.322s</span></span><br><span class="line"><span class="comment">    */</span></span><br></pre></td></tr></table></figure>

<h2 id="六、性能比较测试"><a href="#六、性能比较测试" class="headerlink" title="六、性能比较测试"></a>六、性能比较测试</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">上面的基准测试只能得到给定操作的绝对耗时，但是在很多性能问题是发生在两个不同操作之间的相对耗时，比如同一个函数处理1000个元素的耗时与处理1万甚至100万个元素的耗时的差别是多少？再或者对于同一个任务究竟使用哪种算法性能最佳？我们通常需要对两个不同算法的实现使用相同的输入来进行基准比较测试。</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">性能比较函数通常是一个带有参数的函数，被多个不同的Benchmark函数传入不同的值来调用</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// split_test.go</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">benchmarkFib</span><span class="params">(b *testing.B, n <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">        <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; b.N; i++ &#123;</span><br><span class="line">            Fib(n)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">BenchmarkFib1</span><span class="params">(b *testing.B)</span></span>  &#123; benchmarkFib(b, <span class="number">1</span>) &#125;</span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">BenchmarkFib2</span><span class="params">(b *testing.B)</span></span>  &#123; benchmarkFib(b, <span class="number">2</span>) &#125;</span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">BenchmarkFib3</span><span class="params">(b *testing.B)</span></span>  &#123; benchmarkFib(b, <span class="number">3</span>) &#125;</span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">BenchmarkFib10</span><span class="params">(b *testing.B)</span></span> &#123; benchmarkFib(b, <span class="number">10</span>) &#125;</span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">BenchmarkFib20</span><span class="params">(b *testing.B)</span></span> &#123; benchmarkFib(b, <span class="number">20</span>) &#125;</span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">BenchmarkFib40</span><span class="params">(b *testing.B)</span></span> &#123; benchmarkFib(b, <span class="number">40</span>) &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// split.go</span></span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">Fib</span><span class="params">(n <span class="keyword">int</span>)</span> <span class="title">int</span></span> &#123;</span><br><span class="line">        <span class="keyword">if</span> n &lt; <span class="number">2</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> n</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> Fib(n<span class="number">-1</span>) + Fib(n<span class="number">-2</span>)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">默认情况下,每个基准测试至少运行1秒。如果在Benchmark函数返回时没有到1秒,则b.N的值会按1,2,5,10,20,50，…增加,并且函数再次运行</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">注意：使用性能比较函数做测试的时候一个容易犯的错误就是把b.N作为输入的大小</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>

<h2 id="七、重置时间"><a href="#七、重置时间" class="headerlink" title="七、重置时间"></a>七、重置时间</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// b.ResetTimer之前的处理不会放到执行时间里，也不会输出到报告中，所以可以在之前做一些不计划作为测试报告的操作。例如：</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BenchmarkSplit</span><span class="params">(b *testing.B)</span></span> &#123;</span><br><span class="line">	time.Sleep(<span class="number">5</span> * time.Second) <span class="comment">// 假设需要做一些耗时的无关操作</span></span><br><span class="line">	b.ResetTimer()              <span class="comment">// 重置计时器</span></span><br><span class="line">	<span class="keyword">for</span> i := <span class="number">0</span>; i &lt; b.N; i++ &#123;</span><br><span class="line">        Split(<span class="string">&quot;a:b:c&quot;</span>, <span class="string">&quot;:&quot;</span>)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="八、并行测试"><a href="#八、并行测试" class="headerlink" title="八、并行测试"></a>八、并行测试</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">func (b *B) RunParallel(body func(*PB))会以并行的方式执行给定的基准测试。</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">RunParallel会创建出多个goroutine，并将b.N分配给这些goroutine执行， 其中goroutine数量的默认值为GOMAXPROCS。用户如果想要增加非CPU受限（non-CPU-bound）基准测试的并行性， 那么可以在RunParallel之前调用SetParallelism 。RunParallel通常会与-cpu标志一同使用。</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">func BenchmarkSplitParallel(b *testing.B) &#123;</span></span><br><span class="line"><span class="comment">	// b.SetParallelism(1) // 设置使用的CPU数</span></span><br><span class="line"><span class="comment">	b.RunParallel(func(pb *testing.PB) &#123;</span></span><br><span class="line"><span class="comment">		for pb.Next() &#123;</span></span><br><span class="line"><span class="comment">			Split(&quot;沙河有沙又有河&quot;, &quot;沙&quot;)</span></span><br><span class="line"><span class="comment">		&#125;</span></span><br><span class="line"><span class="comment">	&#125;)</span></span><br><span class="line"><span class="comment">&#125;</span></span><br><span class="line"><span class="comment">执行一下基准测试：</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">split $ go test -bench=.</span></span><br><span class="line"><span class="comment">goos: darwin</span></span><br><span class="line"><span class="comment">goarch: amd64</span></span><br><span class="line"><span class="comment">pkg: github.com/Q1mi/studygo/code_demo/test_demo/split</span></span><br><span class="line"><span class="comment">BenchmarkSplit-8                10000000               131 ns/op</span></span><br><span class="line"><span class="comment">BenchmarkSplitParallel-8        50000000                36.1 ns/op</span></span><br><span class="line"><span class="comment">PASS</span></span><br><span class="line"><span class="comment">ok      github.com/Q1mi/studygo/code_demo/test_demo/split       3.308s</span></span><br><span class="line"><span class="comment">还可以通过在测试命令后添加-cpu参数如go test -bench=. -cpu 1来指定使用的CPU数量。</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>

<h2 id="九、Setup与TearDown"><a href="#九、Setup与TearDown" class="headerlink" title="九、Setup与TearDown"></a>九、Setup与TearDown</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br></pre></td><td class="code"><pre><span class="line">测试程序有时需要在测试之前进行额外的设置（setup）或在测试之后进行拆卸（teardown）。</span><br><span class="line"></span><br><span class="line">TestMain</span><br><span class="line">通过在*_test.<span class="keyword">go</span>文件中定义TestMain函数来可以在测试之前进行额外的设置（setup）或在测试之后进行拆卸（teardown）操作。</span><br><span class="line"></span><br><span class="line">如果测试文件包含函数:<span class="function"><span class="keyword">func</span> <span class="title">TestMain</span><span class="params">(m *testing.M)</span>那么生成的测试会先调用 <span class="title">TestMain</span><span class="params">(m)</span>，然后再运行具体测试。<span class="title">TestMain</span>运行在主<span class="title">goroutine</span>中, 可以在调用 <span class="title">m</span>.<span class="title">Run</span>前后做任何设置（<span class="title">setup</span>）和拆卸（<span class="title">teardown</span>）。退出测试的时候应该使用<span class="title">m</span>.<span class="title">Run</span>的返回值作为参数调用<span class="title">os</span>.<span class="title">Exit</span>。</span></span><br><span class="line"></span><br><span class="line">一个使用TestMain来设置Setup和TearDown的示例如下：</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">TestMain</span><span class="params">(m *testing.M)</span></span> &#123;</span><br><span class="line">	fmt.Println(<span class="string">&quot;write setup code here...&quot;</span>) <span class="comment">// 测试之前的做一些设置</span></span><br><span class="line">	<span class="comment">// 如果 TestMain 使用了 flags，这里应该加上flag.Parse()</span></span><br><span class="line">	retCode := m.Run()                         <span class="comment">// 执行测试</span></span><br><span class="line">	fmt.Println(<span class="string">&quot;write teardown code here...&quot;</span>) <span class="comment">// 测试之后做一些拆卸工作</span></span><br><span class="line">	os.Exit(retCode)                           <span class="comment">// 退出测试</span></span><br><span class="line">&#125;</span><br><span class="line">需要注意的是：在调用TestMain时, flag.Parse并没有被调用。所以如果TestMain 依赖于command-line标志 (包括 testing 包的标记), 则应该显示的调用flag.Parse。</span><br><span class="line"></span><br><span class="line">子测试的Setup与Teardown</span><br><span class="line">有时候我们可能需要为每个测试集设置Setup与Teardown，也有可能需要为每个子测试设置Setup与Teardown。下面我们定义两个函数工具函数如下：</span><br><span class="line"></span><br><span class="line"><span class="comment">// 测试集的Setup与Teardown</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">setupTestCase</span><span class="params">(t *testing.T)</span> <span class="title">func</span><span class="params">(t *testing.T)</span></span> &#123;</span><br><span class="line">	t.Log(<span class="string">&quot;如有需要在此执行:测试之前的setup&quot;</span>)</span><br><span class="line">	<span class="keyword">return</span> <span class="function"><span class="keyword">func</span><span class="params">(t *testing.T)</span></span> &#123;</span><br><span class="line">		t.Log(<span class="string">&quot;如有需要在此执行:测试之后的teardown&quot;</span>)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 子测试的Setup与Teardown</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">setupSubTest</span><span class="params">(t *testing.T)</span> <span class="title">func</span><span class="params">(t *testing.T)</span></span> &#123;</span><br><span class="line">	t.Log(<span class="string">&quot;如有需要在此执行:子测试之前的setup&quot;</span>)</span><br><span class="line">	<span class="keyword">return</span> <span class="function"><span class="keyword">func</span><span class="params">(t *testing.T)</span></span> &#123;</span><br><span class="line">		t.Log(<span class="string">&quot;如有需要在此执行:子测试之后的teardown&quot;</span>)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line">使用方式如下：</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">TestSplit</span><span class="params">(t *testing.T)</span></span> &#123;</span><br><span class="line">	<span class="keyword">type</span> test <span class="keyword">struct</span> &#123; <span class="comment">// 定义test结构体</span></span><br><span class="line">		input <span class="keyword">string</span></span><br><span class="line">		sep   <span class="keyword">string</span></span><br><span class="line">		want  []<span class="keyword">string</span></span><br><span class="line">	&#125;</span><br><span class="line">	tests := <span class="keyword">map</span>[<span class="keyword">string</span>]test&#123; <span class="comment">// 测试用例使用map存储</span></span><br><span class="line">		<span class="string">&quot;simple&quot;</span>:      &#123;input: <span class="string">&quot;a:b:c&quot;</span>, sep: <span class="string">&quot;:&quot;</span>, want: []<span class="keyword">string</span>&#123;<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>&#125;&#125;,</span><br><span class="line">		<span class="string">&quot;wrong sep&quot;</span>:   &#123;input: <span class="string">&quot;a:b:c&quot;</span>, sep: <span class="string">&quot;,&quot;</span>, want: []<span class="keyword">string</span>&#123;<span class="string">&quot;a:b:c&quot;</span>&#125;&#125;,</span><br><span class="line">		<span class="string">&quot;more sep&quot;</span>:    &#123;input: <span class="string">&quot;abcd&quot;</span>, sep: <span class="string">&quot;bc&quot;</span>, want: []<span class="keyword">string</span>&#123;<span class="string">&quot;a&quot;</span>, <span class="string">&quot;d&quot;</span>&#125;&#125;,</span><br><span class="line">		<span class="string">&quot;leading sep&quot;</span>: &#123;input: <span class="string">&quot;沙河有沙又有河&quot;</span>, sep: <span class="string">&quot;沙&quot;</span>, want: []<span class="keyword">string</span>&#123;<span class="string">&quot;&quot;</span>, <span class="string">&quot;河有&quot;</span>, <span class="string">&quot;又有河&quot;</span>&#125;&#125;,</span><br><span class="line">	&#125;</span><br><span class="line">	teardownTestCase := setupTestCase(t) <span class="comment">// 测试之前执行setup操作</span></span><br><span class="line">	<span class="keyword">defer</span> teardownTestCase(t)            <span class="comment">// 测试之后执行testdoen操作</span></span><br><span class="line"></span><br><span class="line">	<span class="keyword">for</span> name, tc := <span class="keyword">range</span> tests &#123;</span><br><span class="line">		t.Run(name, <span class="function"><span class="keyword">func</span><span class="params">(t *testing.T)</span></span> &#123; <span class="comment">// 使用t.Run()执行子测试</span></span><br><span class="line">			teardownSubTest := setupSubTest(t) <span class="comment">// 子测试之前执行setup操作</span></span><br><span class="line">			<span class="keyword">defer</span> teardownSubTest(t)           <span class="comment">// 测试之后执行testdoen操作</span></span><br><span class="line">			got := Split(tc.input, tc.sep)</span><br><span class="line">			<span class="keyword">if</span> !reflect.DeepEqual(got, tc.want) &#123;</span><br><span class="line">				t.Errorf(<span class="string">&quot;excepted:%#v, got:%#v&quot;</span>, tc.want, got)</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line">测试结果如下：</span><br><span class="line"></span><br><span class="line">split $ <span class="keyword">go</span> test -v</span><br><span class="line">=== RUN   TestSplit</span><br><span class="line">=== RUN   TestSplit/simple</span><br><span class="line">=== RUN   TestSplit/wrong_sep</span><br><span class="line">=== RUN   TestSplit/more_sep</span><br><span class="line">=== RUN   TestSplit/leading_sep</span><br><span class="line">--- PASS: TestSplit (<span class="number">0.00</span>s)</span><br><span class="line">    split_test.<span class="keyword">go</span>:<span class="number">71</span>: 如有需要在此执行:测试之前的setup</span><br><span class="line">    --- PASS: TestSplit/simple (<span class="number">0.00</span>s)</span><br><span class="line">        split_test.<span class="keyword">go</span>:<span class="number">79</span>: 如有需要在此执行:子测试之前的setup</span><br><span class="line">        split_test.<span class="keyword">go</span>:<span class="number">81</span>: 如有需要在此执行:子测试之后的teardown</span><br><span class="line">    --- PASS: TestSplit/wrong_sep (<span class="number">0.00</span>s)</span><br><span class="line">        split_test.<span class="keyword">go</span>:<span class="number">79</span>: 如有需要在此执行:子测试之前的setup</span><br><span class="line">        split_test.<span class="keyword">go</span>:<span class="number">81</span>: 如有需要在此执行:子测试之后的teardown</span><br><span class="line">    --- PASS: TestSplit/more_sep (<span class="number">0.00</span>s)</span><br><span class="line">        split_test.<span class="keyword">go</span>:<span class="number">79</span>: 如有需要在此执行:子测试之前的setup</span><br><span class="line">        split_test.<span class="keyword">go</span>:<span class="number">81</span>: 如有需要在此执行:子测试之后的teardown</span><br><span class="line">    --- PASS: TestSplit/leading_sep (<span class="number">0.00</span>s)</span><br><span class="line">        split_test.<span class="keyword">go</span>:<span class="number">79</span>: 如有需要在此执行:子测试之前的setup</span><br><span class="line">        split_test.<span class="keyword">go</span>:<span class="number">81</span>: 如有需要在此执行:子测试之后的teardown</span><br><span class="line">    split_test.<span class="keyword">go</span>:<span class="number">73</span>: 如有需要在此执行:测试之后的teardown</span><br><span class="line">=== RUN   ExampleSplit</span><br><span class="line">--- PASS: ExampleSplit (<span class="number">0.00</span>s)</span><br><span class="line">PASS</span><br><span class="line">ok      github.com/Q1mi/studygo/code_demo/test_demo/split       <span class="number">0.006</span>s</span><br></pre></td></tr></table></figure>

<h2 id="十、示例函数"><a href="#十、示例函数" class="headerlink" title="十、示例函数"></a>十、示例函数</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 示例函数的格式</span><br><span class="line">    <span class="comment">// 被go test特殊对待的第三种函数就是示例函数，它们的函数名以Example为前缀。它们既没有参数也没有返回值。标准格式如下：</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">ExampleName</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="comment">// ...</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="number">2.</span> 示例函数示例</span><br><span class="line">    下面的代码是我们为Split函数编写的一个示例函数：</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">func</span> <span class="title">ExampleSplit</span><span class="params">()</span></span> &#123;</span><br><span class="line">        fmt.Println(split.Split(<span class="string">&quot;a:b:c&quot;</span>, <span class="string">&quot;:&quot;</span>))</span><br><span class="line">        fmt.Println(split.Split(<span class="string">&quot;沙河有沙又有河&quot;</span>, <span class="string">&quot;沙&quot;</span>))</span><br><span class="line">        <span class="comment">// Output:</span></span><br><span class="line">        <span class="comment">// [a b c]</span></span><br><span class="line">        <span class="comment">// [ 河有 又有河]</span></span><br><span class="line">    &#125;</span><br><span class="line">	</span><br><span class="line"><span class="number">3.</span> 为你的代码编写示例代码有如下三个用处：</span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	示例函数能够作为文档直接使用，例如基于web的godoc中能把示例函数与对应的函数或包相关联。</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    示例函数只要包含了// Output:也是可以通过go test运行的可执行测试。</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    split $ go test -run Example</span></span><br><span class="line"><span class="comment">    PASS</span></span><br><span class="line"><span class="comment">    ok      github.com/Q1mi/studygo/code_demo/test_demo/split       0.006s</span></span><br><span class="line"><span class="comment">    示例函数提供了可以直接运行的示例代码，可以直接在golang.org的godoc文档服务器上使用Go Playground运行示例代码</span></span><br><span class="line"><span class="comment">	*/</span></span><br></pre></td></tr></table></figure>


            </div>

            <!-- Post Comments -->
            
    <!-- 使用 DISQUS_CLICK -->
<div id="disqus-comment">
    <div id="disqus_thread"></div>

<!-- add animation -->
<style>
	.disqus_click_btn {
            line-height: 30px;
            margin: 0;
            min-width: 50px;
            padding: 0 14px;
            display: inline-block;
            font-family: "Roboto", "Helvetica", "Arial", sans-serif;
            font-size: 14px;
            font-weight: 400;
            text-transform: uppercase;
            letter-spacing: 0;
            overflow: hidden;
            will-change: box-shadow;
            transition: box-shadow .2s cubic-bezier(.4, 0, 1, 1), background-color .2s cubic-bezier(.4, 0, .2, 1), color .2s cubic-bezier(.4, 0, .2, 1);
            outline: 0;
            cursor: pointer;
            text-decoration: none;
            text-align: center;
            vertical-align: middle;
            border: 0;
            background: rgba(158, 158, 158, .2);
            box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12);
            color: #fff;
            background-color: #7EC0EE;
            text-shadow: 0
        }
</style>
	
<div class="btn_click_load" id="disqus_bt"> 
    <button class="disqus_click_btn">点击查看评论</button>
</div>

<!--
<script type="text/javascript">
$('.btn_click_load').click(function() {
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'http-miccall-tech'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
      var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
      dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
      (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();

    document.getElementById('disqus_bt').style.display = "none";
});
</script>
-->
<script type="text/javascript">
    var disqus_config = function () {
        this.page.url = 'https://gitee.com/AmeX/amelin-ting.git/2018/06/10/Go%E6%B5%8B%E8%AF%95------%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/';  // Replace PAGE_URL with your page's canonical URL variable
        this.page.identifier = 'https://gitee.com/AmeX/amelin-ting.git/2018/06/10/Go%E6%B5%8B%E8%AF%95------%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/'; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
    };
</script>

<script type="text/javascript">
    $('.btn_click_load').click(function() {  //click to load comments
        (function() { // DON'T EDIT BELOW THIS LINE
            var d = document;
            var s = d.createElement('script');
            s.src = '//http-miccall-tech.disqus.com/embed.js';
            s.setAttribute('data-timestamp', + new Date());
            (d.head || d.body).appendChild(s);
        })();
        $('.btn_click_load').css('display','none');
    });
</script>
</div>
<style>
    #disqus-comment{
        background-color: #eee;
        padding: 2pc;
    }
</style>


        </div>
        <!-- Copyright 版权 start -->
                <div id="copyright">
            <ul>
                <li>&copy;Powered By <a target="_blank" rel="noopener" href="https://hexo.io/zh-cn/" style="border-bottom: none;">hexo</a></li>
                <li>Design: <a target="_blank" rel="noopener" href="http://miccall.tech " style="border-bottom: none;">miccall</a></li>
            </ul>
            
                <span id="busuanzi_container_site_pv">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span>
			
        </div>
    </div>
</body>



 	
</html>
